goog.require('goog.Uri');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.style');

/** @const */ var TESTING = true;
///** @const */ var g = console.log;

/** @const */ var g = function(){};

var LOG_URL = null;


if(TESTING) {
    g_canvas = null;
    heatmapShown = false;
    pts = [];
    data = {points:pts};
    LOG_URL = 'http://localhost:5000/c';

} else {
//    LOG_URL = 'http://localhost:5000/c';
    LOG_URL = 'http://s3.amazonaws.com/com.sharedflame.q2/c';
}

function plot(x, y, color) {
    var pt = document.createElement('div');
    pt.style.position = 'absolute';
    pt.style.border = '0px dotted blue';
    pt.style.width = '6px';
    pt.style.height = '6px';
    pt.style.backgroundColor = color || 'red';
    pt.style.left = x + 'px';
    pt.style.top = y + 'px';
    pt.style.zIndex = 1000000;

    document.body.appendChild(pt);
}

function point_to_pixel(p) {
    if(p.parentID) {

        var e = goog.dom.$(p.parentID);
        var sz = goog.style.getSize(e);
        var ps = goog.style.getPosition(e);

        return {
            x: parseInt(p.x * sz.width  / 255.0 + ps.x),
            y: parseInt(p.y * sz.height / 255.0 + ps.y)
        };
    }

    return p;
}

function postData(post) {
    var u = new goog.Uri(LOG_URL);
    u.setParameterValue('x', post.x);
    u.setParameterValue('y', post.y);
    u.setParameterValue('url', post.url);

    if (post.parentID) {
        u.setParameterValue('pid', post.parentID);
    }

    var i = document.createElement("img");
    i.style.display = "none";
    i.src = u.toString();

    if (post.tagname == goog.dom.TagName.A) {
        var zzz = new Date().getTime();
        while (((new Date().getTime()) - zzz) < 500) {
        }
    }
}

function clicked(e) {

    var scroll = goog.dom.getDocumentScroll(); 

    var x = parseInt(e.clientX) + scroll.x;
    var y = parseInt(e.clientY) + scroll.y;
    var target = e.target;
    var parentID = null;

    // 1. find an element to anchor against (absolute positions if none found)
    //    * some unique way to identify object
    //      * id attribute
    //      * href and other attributes (class, etc.)
    if (target.id) {
        parentID = target.id;
        var sz = goog.style.getSize(target);
        var ps = goog.style.getPosition(target);
        x -= ps.x;
        y -= ps.y;
        x *= 255.0;
        y *= 255.0; 
        x /= sz.width;
        y /= sz.height;
        x = parseInt(x);
        y = parseInt(y);
    }

    // 2. if proper container found, scale x,y to the box of the target (or some other ancestor?)
    //    * add the parent attribute to point metadata
    //    * 

    //    g('event X,Y:', x, y, e.currentTarget, '---------', scroll, op);


    if(TESTING && e.isButton(2)) {
        if(g_canvas) {
            document.body.removeChild(g_canvas);
            g_canvas = null;
        } else {
            showHeatMap(data);
        }
        return;
    }

    var post = {
        url: document.location.href,
        x: x,
        y: y,
        parentID: parentID,
        tagname: e.target.tagName
    };

    if(TESTING) {
        var p = goog.style.getPageOffset(e.target);

        plot(p.x, p.y, 'green');

        pts.push(post);

        var pl = point_to_pixel(post);
        plot(pl.x, pl.y);
    }

    postData(post);
}

function loadHeatMapData() {
    window['showHeatMap'] = showHeatMap;

    var e = document.createElement("script");

    if(TESTING) {
//    if (true) {
        e.src = 'http://localhost:5000/spots_f205d141e4f369e2355e2105890c80df1cc4ff76195b9e52e4c4ca2641bdda89.js';
//        e.src = 'http://localhost:5000/spots_96112a9bcc2894b703e363db5056e54b5c4706d04ea4d6be9f15b1c65463d96f.js';

    } else {
        e.src = 'http://processmethis.com/SharedFlame/getpoints.php?t='
                + (new Date().getTime()) + '&url='
                + document.location.href;
    }

    document.body.appendChild(e);
}


//var COLORS = [
//    [44, 44, 155],
//    [44, 44, 255],
//    [255, 0, 0],
//    [255, 255, 0],
//    [255, 255, 255],
//
//    [255, 255, 255] // Note:  last one is a dummy
//];


/** @const */ var COLORS = [
    [0, 0, 0],
    [50, 30,0],
    [255, 155, 0],
    [255, 255, 0],
    [255, 255, 255],

    [255, 255, 255] // Note:  last one is a dummy
];

var CLMINUS1 = (COLORS.length - 2);


function multicolorHeatMap(value) {
    var n = (value * CLMINUS1);
    var i = Math.floor(n);
    var d = (n - i);

    var c = COLORS[i];
    var xx = COLORS[i+1];
    var omd = 1.0 - d;

    var r = parseInt(c[0] * omd + xx[0] * d);
    var g = parseInt(c[1] * omd + xx[1] * d);
    var b = parseInt(c[2] * omd + xx[2] * d);

    return [r, g, b];
}

function createColorMapBand(HORIZ, w, pix) {
    var HEIGHT = 10;
    for (var i = 0; i < HORIZ; i++) {
        var val = i / HORIZ;

        for (var j = 0; j < HEIGHT; j++) {
            var o = (i * 4) + (j * w * 4);
            var col = multicolorHeatMap(val);
            pix[o] = parseInt(col[0]);
            pix[o + 1] = parseInt(col[1]);
            pix[o + 2] = parseInt(col[2]);
            pix[o + 3] = 255;
        }
    }
}

function showHeatMap(data) {

    var c = document.createElement('canvas');

    if(TESTING) {
        g_canvas = c;
    }

    var b = document.body;

    var w = b.offsetWidth;
    var h = b.offsetHeight;
    c.style.position = 'absolute';
    c.style.left = '0';
    c.style.top = '0';
    c.style.width = b.offsetWidth + 'px';
    c.style.height = b.offsetHeight + 'px'
    c.style.zIndex = 9999999;
    c.width = b.offsetWidth;
    c.height = b.offsetHeight;

    document.body.appendChild(c);

    var context = c.getContext('2d');
    var imgd, x = 0,  y = 0;
    imgd = context.createImageData(w, h);

    var pix = imgd.data;
    var CS = data['points'];

    g('creating empty',w,h);

    // create 2d
    var a = Array(w);
    for(var i=0;i<w;i++){
        var ha = a[i] = Array(h);
        for(var j=0;j<h;j++){
            ha[j] = 0;
        }
    }

    g('storing');
    // store values
    for(var i=0; i < CS.length; i++) {
        var pp = CS[i];
        pp = point_to_pixel(pp);

        var xx = pp.x;
        var yy = pp.y;

        var XD = 20;
        var YD = 20;
        for(var xd=-XD;xd<=XD;xd++){
            for(var yd=-YD;yd<=YD;yd++) {
                var zx = xx + xd;
                var zy = yy + yd;
                if((zx >=0)&&
                   (zy >=0)&&
                   (zx < w)&&
                    (zy < h)) {

                    var l = Math.sqrt(xd*xd + yd*yd) / XD;
                    if(l <= 1.0) {
                        a[zx][zy] += 1.0 - l;
                    }
                }
            }
        }
    }

    // normalize ranges
    g('normali');
    var max = 0;
    for(var i=0;i<w;i++){
        var ha = a[i];
        for(var j=0;j<h;j++){
            if(ha[j] > max) {
                max = ha[j];
            }
        }
    }

    g('rendering pixel')


    var QUANT = 90;
    var cache = new Array(QUANT);

    for(var i=0;i<w;i++) {
        var ha = a[i];
        for(var j=0;j<h;j++){
            var l = ha[j];
            var o = (i * 4) + (j * w * 4);

            if(l==0) {
                pix[o]   = COLORS[0][0];
                pix[o+1] = COLORS[0][1];
                pix[o+2] = COLORS[0][2];
                pix[o+3] = 100;
                continue;
            }

            var ggg = l/max;
            var idx = Math.floor(ggg * QUANT);
            var col = cache[idx];
            if(!col) {
                col = multicolorHeatMap(ggg);
                cache[idx] = col;
            }

            pix[o]   = col[0];
            pix[o+1] = col[1];
            pix[o+2] = col[2];
            pix[o+3] = 100;
        }
    }

    g('DONE rendering');

//    if(TESTING) {
        createColorMapBand(QUANT, w, pix);
//    }


    context.putImageData(imgd, x, y);
}

function shouldShowHeatMap() {
    return (window.location && window.location.hash && window.location.hash.match(/sfoverlay/));
}

function setupDocumentClickHandler() {
    if(shouldShowHeatMap()) {
        goog.events.listen(document, 'DOMContentLoaded', loadHeatMapData);
    } else {
        goog.events.listen(document, goog.events.EventType.CLICK, clicked, true);
    }

    g('setup done')
}

if(TESTING) {
    setTimeout(function(){setupDocumentClickHandler();if(shouldShowHeatMap()) {loadHeatMapData();}}, 3000);

} else {
    setupDocumentClickHandler();    
}